#include "RdfsXmlHandler.h"
#include <list>
#include "dal/XmlUtil.h"

namespace xpm {
	RdfsXmlHandler::RdfsXmlHandler(Project* project, DOMDocument* doc, string baseName): _project(project),  XmlHandler(doc), _baseName(baseName) {
		//_doc->getDoctype()->getEntities();
		//DOMNamedNodeMap* attrs = _doc->getDocumentElement()->getAttributes();
		//_cdata = _doc->createCDATASection(L"ssdfsdf&&&&&&");
		//_doc->getDocumentElement()->appendChild(_cdata);
	}

	void RdfsXmlHandler::Parse() {
		DOMElement* xmlRoot = _doc->getDocumentElement();
		DOMNamedNodeMap* map = xmlRoot->getAttributes();
		DOMNode* node = NULL;
	}

	void RdfsXmlHandler::Serialize() {		
		SerializeClasses();
		//to do: parse the attributes

		/*std::list<XpmTermBlock*> blocks = _xpmdoc->GetTermBlocks();
		DOMElement* nodeElement = NULL;
		XMLCh* blockName = XMLString::transcode("Block");
		for(std::list<XpmTermBlock*>::iterator it = blocks.begin(); it != blocks.end(); ++it) {
		nodeElement = _doc->createElement(blockName);
		xmlRoot->appendChild(nodeElement);
		BlockXmlHandler blockHandler(_doc, nodeElement, *it);
		blockHandler.Serialize();
		}
		XMLString::release(&blockName);*/
	}

	void RdfsXmlHandler::SerializeClasses() {
		ClsesMap map = _project->knowledgeBase()->clses();
		for(ClsesIter it = map.begin(); it != map.end(); ++it) {
			DOMElement* nodeElement = _doc->createElement(L"rdfs:Class");
			
			_doc->getDocumentElement()->appendChild(nodeElement);
			//nodeElement->setPrefix(L"rdfs");
			DOMNamedNodeMap* attrs = nodeElement->getAttributes();
			//attrs->setNamedItem(attrAbout);
			//attrAbout->setPrefix(L"rdfs");

			
		
			DOMAttr* attrAbout = _doc->createAttribute(L"rdf:about");
			DOMEntityReference* baseEntity = _doc->createEntityReference(X(_baseName.c_str()));
			attrAbout->appendChild(baseEntity);
			DOMText* textAbout = _doc->createTextNode(X(it->second->name().c_str()));
			attrAbout->appendChild(textAbout);
			//attrAbout->setNodeValue(X(it->second->name().c_str()));
			//attrAbout->appendChild(X(it->second->name().c_str()));
			attrs->setNamedItem(attrAbout);
			
			DOMAttr* attrLabel = _doc->createAttribute(L"rdfs:label");
			attrs->setNamedItem(attrLabel);
			//attrLabel->setPrefix(L"rdfs");
			string labelValue = it->second->name();
			attrLabel->setNodeValue(X(labelValue.c_str()));

			DOMElement* subclassof = _doc->createElement(L"rdfs:subClassOf");
			nodeElement->appendChild(subclassof);

			DOMAttr* attrResource = _doc->createAttribute(L"rdf:resource");
			subclassof->getAttributes()->setNamedItem(attrResource);
			if("THING" == it->second->superCls()->name()) {
				DOMEntityReference* rdfsEntity = _doc->createEntityReference(L"rdfs");
				attrResource->appendChild(rdfsEntity);
				DOMText* textRdfs = _doc->createTextNode(L"Resource");
				attrResource->appendChild(textRdfs);
			}else {
				DOMEntityReference* baseEntity = _doc->createEntityReference(X(_baseName.c_str()));		
				attrResource->appendChild(baseEntity);
				DOMText* textSupername = _doc->createTextNode(X(it->second->superCls()->name().c_str()));
				attrResource->appendChild(textSupername);
			}	
			SerializeSlots(it->second);
		}
	}

	void RdfsXmlHandler::SerializeSlots(Cls* cls) {
		vector<Slot*> map = cls->directTempleteSlots();
		for(vector<Slot*>::iterator it = map.begin(); it != map.end(); ++it) {
			DOMElement* nodeElement = _doc->createElement(L"rdf:Property");
			_doc->getDocumentElement()->appendChild(nodeElement);
			//nodeElement->setPrefix(L"rdfs");
			DOMNamedNodeMap* attrs = nodeElement->getAttributes();
			//attribute about
			DOMAttr* attrAbout = _doc->createAttribute(L"rdf:about");
			attrs->setNamedItem(attrAbout);
			DOMEntityReference* baseEntity = _doc->createEntityReference(X(_baseName.c_str()));
			attrAbout->appendChild(baseEntity);
			DOMText* textAbout = _doc->createTextNode(X((*it)->name().c_str()));
			attrAbout->appendChild(textAbout);

			//attribute maxCardinality
			DOMAttr* attrMax = _doc->createAttribute(L"a:maxCardinality");
			attrs->setNamedItem(attrMax);
			//attrLabel->setPrefix(L"rdfs");
			if((*it)->allowsmultipleValues()) {
				char maxnum[100];
				_itoa_s((*it)->maxnum(), maxnum, 10);
			    attrMax->setNodeValue(X(maxnum));
				DOMAttr* attrMin = _doc->createAttribute(L"a:minCardinality");
				attrs->setNamedItem(attrMin);
				char minnum[100];
				_itoa_s((*it)->minnum(), minnum, 10);
				attrMin->setNodeValue(X(minnum));
			}else {
				attrMax->setNodeValue(L"1");
			}

			//attribute label
			DOMAttr* attrLabel = _doc->createAttribute(L"rdfs:label");
			attrs->setNamedItem(attrLabel);
			//attrLabel->setPrefix(L"rdfs");
			string labelValue =  (*it)->name();
			attrLabel->setNodeValue(X(labelValue.c_str()));

			// child nodes, domain & range
			DOMElement* domain = _doc->createElement(L"rdfs:domain");
			nodeElement->appendChild(domain);


			DOMNamedNodeMap* attrsDomain = domain->getAttributes();
			DOMAttr* attrResource = _doc->createAttribute(L"rdf:resource");
			attrsDomain->setNamedItem(attrResource);
			baseEntity = _doc->createEntityReference(X(_baseName.c_str()));		
			attrResource->appendChild(baseEntity);
			DOMText* textCls = _doc->createTextNode(X(cls->name().c_str()));
			attrResource->appendChild(textCls);

			DOMElement* range = _doc->createElement(L"rdfs:range");
			nodeElement->appendChild(range);

			DOMNamedNodeMap* attrsRange = range->getAttributes();
			DOMAttr* attrResourceRange = _doc->createAttribute(L"rdf:resource");
			attrsRange->setNamedItem(attrResourceRange);
			ValueType vt = (*it)->valueType();
			switch(vt) {
			case STRING: {
				DOMEntityReference* rdfsEntity = _doc->createEntityReference(L"rdfs");
				attrResourceRange->appendChild(rdfsEntity);
				DOMText* textLiteral = _doc->createTextNode(L"Literal");
				attrResourceRange->appendChild(textLiteral);
				break;
						 }
			case BOOLEAN: {
				DOMEntityReference* xsdEntity = _doc->createEntityReference(L"xsd");
				attrResourceRange->appendChild(xsdEntity);
				DOMText* textLiteral = _doc->createTextNode(L"boolean");
				attrResourceRange->appendChild(textLiteral);
				break;
						  }
			case FLOAT: {
				DOMEntityReference* xsdEntity = _doc->createEntityReference(L"xsd");
				attrResourceRange->appendChild(xsdEntity);
				DOMText* textLiteral = _doc->createTextNode(L"float");
				attrResourceRange->appendChild(textLiteral);
				break;
						}
			case INTEGER: {
				DOMEntityReference* xsdEntity = _doc->createEntityReference(L"xsd");
				attrResourceRange->appendChild(xsdEntity);
				DOMText* textLiteral = _doc->createTextNode(L"integer");
				attrResourceRange->appendChild(textLiteral);
				break;
						} 
			case SYMBOL: {
				DOMEntityReference* rdfsEntity = _doc->createEntityReference(L"rdfs");
				attrResourceRange->appendChild(rdfsEntity);
				DOMText* textLiteral = _doc->createTextNode(L"Symbol");
				attrResourceRange->appendChild(textLiteral);
				break;
						} 
			}
		}
	}
}